//自定义网络传输协议
package socket

import (
	"bytes"
	"encoding/binary"
	"net"
)

//消息对象
type Msg struct {
	Conn    net.Conn
	Message []byte
}

const (
	ConstHeader       = "lcfgly::protocol/"
	ConstHeaderLength = len(ConstHeader)
	ConstMsgLength    = 4
)

//整型转换成字节
func IntToBytes(n int) []byte {
	x := int32(n)
	byteBuffer := bytes.NewBuffer([]byte{})
	binary.Write(byteBuffer, binary.LittleEndian, x)
	return byteBuffer.Bytes()
}

//直接转换成整型
func BytesToInt(b []byte) int {
	bytesBuffer := bytes.NewBuffer(b)
	var x int32
	binary.Read(bytesBuffer, binary.LittleEndian, &x)
	return int(x)
}

//封包
func Enpack(message []byte) []byte {
	return append(append([]byte(ConstHeader), IntToBytes(len(message))...), message...)
}

//解包
func Depack(buffer []byte, Conn net.Conn, readerChannel chan Msg) []byte {
	length := len(buffer)
	var i int
	for i = 0; i < length; {
		if length < i+ConstHeaderLength+ConstMsgLength { //整体长度小于消息头长度,返回
			break
		}
		if string(buffer[i:i+ConstHeaderLength]) == ConstHeader { //标识一条新消息的开始
			messageLength := BytesToInt(buffer[i+ConstHeaderLength : i+ConstHeaderLength+ConstMsgLength])
			if length < i+ConstHeaderLength+ConstMsgLength+messageLength { //一条消息整体长度不完整,返回等待后续消息
				break
			}
			data := buffer[i+ConstHeaderLength+ConstMsgLength : i+ConstHeaderLength+ConstMsgLength+messageLength]
			i = i + ConstHeaderLength + ConstMsgLength + messageLength //直接跳过中间消息循环
			mesg := Msg{Conn, data}
			readerChannel <- mesg //处理消息
		} else {
			i = i + 1
		}
	}
	if i == length {
		return make([]byte, 0) //如果消息正好解析完成返回空数组
	}
	return buffer[i:] //返回未解析的数组
}
